package zdream.pmfield.test.stage.roll;

import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.atomic.AtomicInteger;

import zdream.pmfield.data.foe.Foe;
import zdream.pmfield.data.foe.MoveTemplate;
import zdream.pmfield.data.foe.VStat;
import zdream.pmfield.stage.StageBuilderForTest;
import zdream.pmfield.stage.director.Roll;
import zdream.pmfield.stage.message.RollReportMessage;
import zdream.pmfield.storage.FoeTemplateStorage;
import zdream.pmfield.test.utils.ResourceConstant;
import zdream.pmfield.stage.StageWrapper;
import zdream.pmfield.test.utils.StageConstant;

import static org.junit.Assert.*;

/**
 * @author Zdream
 * @date 2023-11-20
 * @since 0.0.1
 */
public class RollCase {
	FoeTemplateStorage storage;

	@Before
	public void before() {
		storage = new FoeTemplateStorage();
		storage.load();
		storage.loadMovesInResource(ResourceConstant.RES_PATH_TEST_MOVES_JSON);
	}

	@Test
	public void testMoveWith100RateFix() {
		MoveTemplate moveWith100RateFix = storage.findMoveById(10000010, 1);
		assertEquals(moveWith100RateFix.name, "肯定成功");

		Foe foe1 = Foe.builder(storage.findFoeById(4))
				.withLevel(20)
				.withMove(moveWith100RateFix)
				.build();
		Foe foe2 = Foe.builder(storage.findFoeById(1))
				.withLevel(20)
				.withMove(moveWith100RateFix)
				.build();
		StageWrapper wrapper = StageBuilderForTest.builder()
				.putFoeToOneSide(foe1)
				.putFoeToAnotherSide(foe2)
				.disableDistanceCheck()
				.withStorage(storage)
				.buildWrapper();
		AtomicInteger count = new AtomicInteger(0);

		wrapper.printBeforeHandleMessage();
		wrapper.onDefaultActionRequest();
		wrapper.onMessage(RollReportMessage.class, reportMessage -> {
			if (!StageConstant.ROLL_TITLE_ACTION.equals(reportMessage.title)) {
				return;
			}
			assertTrue(reportMessage.rolls.length == 1);

			final Roll roll = reportMessage.rolls[0];
			assertEquals(roll.baseValue, reportMessage.foe.vStats[VStat.LUCK.ordinal()] + 100);
			assertTrue(roll.baseValue > 100);
			assertEquals(roll.checkValue, 101);
			assertEquals(roll.baseValue, roll.fixedBaseValue);
			assertTrue(roll.result);

			count.incrementAndGet();
		});

		wrapper.setNextRollCheckValue(101);
		wrapper.runUntil(stage0 -> count.get() >= 10);
	}

	@Test
	public void testMoveWithMinus100RateFix() {
		MoveTemplate moveWith100RateFix = storage.findMoveById(10000011, 1);
		assertEquals(moveWith100RateFix.name, "肯定失败");

		Foe foe1 = Foe.builder(storage.findFoeById(4))
				.withLevel(20)
				.withMove(moveWith100RateFix)
				.build();
		Foe foe2 = Foe.builder(storage.findFoeById(1))
				.withLevel(20)
				.withMove(moveWith100RateFix)
				.build();
		StageWrapper wrapper = StageBuilderForTest.builder()
				.putFoeToOneSide(foe1)
				.putFoeToAnotherSide(foe2)
				.disableDistanceCheck()
				.withStorage(storage)
				.buildWrapper();
		AtomicInteger count = new AtomicInteger(0);

		wrapper.printBeforeHandleMessage();
		wrapper.onDefaultActionRequest();
		wrapper.onMessage(RollReportMessage.class, reportMessage -> {
			if (!StageConstant.ROLL_TITLE_ACTION.equals(reportMessage.title)) {
				return;
			}
			assertTrue(reportMessage.rolls.length == 1);

			final Roll roll = reportMessage.rolls[0];
			assertEquals(roll.baseValue, reportMessage.foe.vStats[VStat.LUCK.ordinal()] - 100);
			assertTrue(roll.baseValue < 100);
			assertEquals(roll.baseValue, roll.fixedBaseValue);
			assertEquals(roll.checkValue, 0);
			assertFalse(roll.result);

			count.incrementAndGet();
		});

		wrapper.setNextRollCheckValue(0);
		wrapper.runUntil(stage0 -> count.get() >= 10);
	}
}
